package com.example.travelgd.service;

import com.example.travelgd.entity.Food;
import com.example.travelgd.repository.FoodMapper;
import com.example.travelgd.util.FwResult;
import com.example.travelgd.websocket.WebSocketServer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class FoodService {

    @Autowired
    private FoodMapper foodMapper;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    private WebSocketServer webSocketServer;

    private static final String FOOD_CACHE_KEY = "travelgd:food";
    private static final long CACHE_EXPIRE_TIME = 5;
    private static final TimeUnit CACHE_EXPIRE_UNIT = TimeUnit.MINUTES;

    /**
     * 生成列表缓存key
     */
    private String generateListCacheKey(Integer categoryId) {
        return FOOD_CACHE_KEY + ":list:" + (categoryId == null ? "all" : categoryId);
    }

    /**
     * 生成详情缓存key
     */
    private String generateDetailCacheKey(Long id) {
        return FOOD_CACHE_KEY + ":detail:" + id;
    }

    /**
     * 获取美食列表
     */
    public List<Food> getFoodList(Integer categoryId, Integer page, Integer pageSize) {
        // 构造缓存key
        String cacheKey = generateListCacheKey(categoryId);

        // 先从缓存获取
        List<Food> cachedList = (List<Food>) redisTemplate.opsForValue().get(cacheKey);
        if (cachedList != null) {
            log.info("从缓存获取美食列表: {}", cachedList);
            return cachedList;
        }

        // 计算分页偏移量
        int offset = (page - 1) * pageSize;

        // 缓存未命中,从数据库查询
        List<Food> foodList;
        if (categoryId != null && categoryId != 0) {
            // 有分类过滤
            foodList = foodMapper.selectByCategoryWithPage(categoryId, offset, pageSize);
        } else {
            // 查询所有启用状态的食物
            foodList = foodMapper.selectAllEnabledWithPage(offset, pageSize);
        }
        log.info("从数据库获取美食列表: {}", foodList);

        // 放入缓存
        redisTemplate.opsForValue().set(cacheKey, foodList,
                CACHE_EXPIRE_TIME, CACHE_EXPIRE_UNIT);

        return foodList;
    }

    /**
     * 获取美食详情
     */
    public Food getFoodDetail(Long id) {
        try {
            // 从缓存获取详情
            String cacheKey = generateDetailCacheKey(id);
            Food cachedFood = (Food) redisTemplate.opsForValue().get(cacheKey);
            if (cachedFood != null) {
                log.info("从缓存获取美食详情: {}", cachedFood);
                return cachedFood;
            }

            // 缓存未命中，从数据库查询
            Food food = foodMapper.selectById(id);
            if (food != null) {
                // 放入缓存
                redisTemplate.opsForValue().set(cacheKey, food,
                        CACHE_EXPIRE_TIME, CACHE_EXPIRE_UNIT);
                log.info("从数据库获取美食详情: {}", food);
            }
            return food;
        } catch (Exception e) {
            log.error("获取美食详情失败, id: {}", id, e);
            throw e;
        }
    }

    /**
     * 添加美食
     */
    public FwResult<Void> addFood(Food food) {
        try {
            // 设置默认值
            food.setCreateTime(LocalDateTime.now());
            food.setUpdateTime(LocalDateTime.now());
            food.setStatus(food.getStatus() == null ? 1 : food.getStatus());
            food.setSales(food.getSales() == null ? 0 : food.getSales());

            if (foodMapper.insert(food) > 0) {
                // 清除缓存并重新加载
                refreshCache();
                // 推送更新消息
                webSocketServer.sendToAll("FOOD_UPDATE");
                log.info("美食添加成功并推送更新消息，ID: {}", food.getId());
                return FwResult.ok();
            }
            return FwResult.failedMsg("添加美食失败");
        } catch (Exception e) {
            log.error("添加美食失败", e);
            return FwResult.failedMsg("添加美食失败");
        }
    }

    /**
     * 更新美食
     */
    public FwResult<Void> updateFood(Food food) {
        try {
            food.setUpdateTime(LocalDateTime.now());
            if (foodMapper.updateById(food) > 0) {
                // 清除缓存
                clearCache();
                // 推送更新消息
                webSocketServer.sendToAll("FOOD_UPDATE");
                log.info("美食更新成功并推送更新消息，ID: {}", food.getId());
                return FwResult.ok();
            }
            return FwResult.failedMsg("更新美食失败");
        } catch (Exception e) {
            log.error("更新美食失败", e);
            return FwResult.failedMsg("更新美食失败");
        }
    }

    /**
     * 删除美食
     */
    public FwResult<Void> deleteFood(Long id) {
        try {
            if (foodMapper.deleteById(id) > 0) {
                // 清除缓存并重新加载
                refreshCache();
                // 推送更新消息
                webSocketServer.sendToAll("FOOD_UPDATE");
                log.info("美食删除成功并推送更新消息，ID: {}", id);
                return FwResult.ok();
            }
            return FwResult.failedMsg("删除美食失败");
        } catch (Exception e) {
            log.error("删除美食失败", e);
            return FwResult.failedMsg("删除美食失败");
        }
    }

    /**
     * 清除所有美食相关缓存
     */
    public void clearCache() {
        try {
            // 获取所有与美食相关的缓存key
            String pattern = FOOD_CACHE_KEY + "*";
            Set<String> keys = redisTemplate.keys(pattern);
            if (keys != null && !keys.isEmpty()) {
                redisTemplate.delete(keys);
                log.info("清除美食缓存成功, keys: {}", keys);
            }
        } catch (Exception e) {
            log.error("清除美食缓存失败", e);
        }
    }

    /**
     * 刷新美食缓存
     */
    public void refreshCache() {
        try {
            // 获取所有分类
            List<Integer> categories = foodMapper.getAllCategories();

            // 清除所有相关缓存
            clearCache();

            // 为每个分类刷新缓存
            for (Integer categoryId : categories) {
                String cacheKey = generateListCacheKey(categoryId);
                List<Food> foodList = foodMapper.selectByCategory(categoryId);
                redisTemplate.opsForValue().set(cacheKey, foodList,
                        CACHE_EXPIRE_TIME, CACHE_EXPIRE_UNIT);
            }

            // 刷新全部列表缓存
            String allCacheKey = generateListCacheKey(null);
            List<Food> allFoodList = foodMapper.selectAllEnabled();
            redisTemplate.opsForValue().set(allCacheKey, allFoodList,
                    CACHE_EXPIRE_TIME, CACHE_EXPIRE_UNIT);

            log.info("刷新美食缓存成功");
            webSocketServer.sendToAll("FOOD_UPDATE");
        } catch (Exception e) {
            log.error("刷新美食缓存失败", e);
        }
    }

    /**
     * 检查缓存是否有效
     */
    public boolean isCacheValid() {
        try {
            String pattern = FOOD_CACHE_KEY + "*";
            Set<String> keys = redisTemplate.keys(pattern);
            return keys != null && !keys.isEmpty();
        } catch (Exception e) {
            log.error("检查缓存状态失败", e);
            return false;
        }
    }
}